/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			cpglibrary.cc
  \date			Nov 2012
  \author		TNick

  \brief		Contains the implementation of CpgLibrary class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<QSettings>
#include	<QFile>
#include	<QUrl>
#include	<QFileDialog>
#include	<QMessageBox>
#include	<QApplication>

#include	<cpg/cpg.h>
#include	<cpg/cpglibrary.h>

#include	<cpg/preferences/prefs.h>

#include	<cpg/logic/cpgdoc.h>
#include	<cpg/logic/pgspace.h>
#include	<cpg/logic/layer/pglayglob.h>
#include	<cpg/logic/layer/pglayspc.h>

#include	<cpg/file-formats/formatmanager.h>
#include	<cpg/file-formats/idrawfile.h>

#include	<cpg/atoms/space/aspaceid.h>
#include	<cpg/atoms/layer/alayid.h>


/*  INCLUDES    ============================================================ */
//
//
//
//
/*  DEFINITIONS    --------------------------------------------------------- */

using namespace cpg;

/*  DEFINITIONS    ========================================================= */
//
//
//
//
/*  DATA    ---------------------------------------------------------------- */

CpgLibrary *		CpgLibrary::uniq_ = NULL;

/*  DATA    ================================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/* ------------------------------------------------------------------------- */
bool CPGSHARED_EXPORT			initCpgLibrary			( void )
{
	PGDBG( PGDBG_LIBRARY, "Requested initialisation of the library" );


	if ( CpgLibrary::unique() == NULL )
	{
		/*Q_INIT_RESOURCE( libcpg );*/
		new CpgLibrary();
	}
	else
	{
		PGDBG2( PGDBG_LIBRARY, "Library already initialised at ",
				CpgLibrary::unique());
	}
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void CPGSHARED_EXPORT			endCpgLibrary			( void )
{
	PGDBG( PGDBG_LIBRARY, "Requested termination of the library" );
	if ( CpgLibrary::unique() == NULL )
	{
		PGDBG( PGDBG_LIBRARY, "Library not initialised or already terminated" );
		return;
	}
	delete CpgLibrary::unique();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgLibrary::CpgLibrary	( void )
	: QObject(), GuiderManager()
{

	Q_ASSERT( uniq_ == NULL );
	uniq_ = this;
	crt_doc_ = NULL;
	b_closing_ = false;
	id_doc_ = 0;

	PGDBG2( PGDBG_CTORDTOR, "Creating library singleton", uniq_ );

	QSettings	stg;
	stg.beginGroup( "CpgLibrary" );


	stg.endGroup();

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgLibrary::~CpgLibrary	( void )
{
	PGDBG2( PGDBG_CTORDTOR, "Destroying library singleton", this );

	Q_ASSERT( uniq_ == this );
	uniq_ = NULL;

	QSettings	stg;
	stg.beginGroup( "CpgLibrary" );


	stg.endGroup();

}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
void			CpgLibrary::setCrtDoc		( CpgDoc * new_val )
{
	if ( uniq_->crt_doc_ != new_val )
	{
		if ( new_val == NULL )
		{
			uniq_->crt_doc_ = NULL;
			emit uniq_->crtDocChanged( NULL );
		}
		else if ( new_val->isHidden() == false )
		{
			uniq_->crt_doc_ = new_val;
			emit uniq_->crtDocChanged( new_val );
			uniq_->ug_.setActiveStack( new_val->undoStack() );
		}
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::setCrtDocNS		( CpgDoc * new_val )
{
	if ( uniq_->crt_doc_ != new_val )
	{
		uniq_->crt_doc_ = new_val;
		uniq_->ug_.setActiveStack( new_val->undoStack() );
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc *			CpgLibrary::normaliseDoc		( BBlocks::UserMsg & um, CpgDoc * doc )
{
	if ( doc != NULL )
		return doc;
	doc = crtDoc();
	if ( doc != NULL )
		return doc;
	um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
				"There is no current document.\n")
			);
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::closeDoc			( BBlocks::UserMsg & um, CpgDoc * doc )
{
	doc = normaliseDoc( um, doc );
	if ( doc == NULL )
		return false;

	int idx = uniq_->lst_doc_.indexOf( doc );
	if ( idx == -1 )
	{
		um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
					"The document to close is not managed by the application.\n")
				);
		return false;
	}

	/* does it has unsaved changes? */
	if ( doc->isModified() )
	{
		int res = QMessageBox::question(
					activeWindow(),
					QObject::tr( "Save changes?" ),
					QObject::tr(
						"File %1\n has unsaved changes.\n\n"
						"Would you like to save these changes now?\n" ),
					QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
					QMessageBox::Yes
					);

		switch ( res )	{
		case	QMessageBox::Yes:		{
			if ( CpgLibrary::saveDocument( um, doc ) == false )
				return false;
			break; }
		case	QMessageBox::No:	{
			break; }
			/*case	QMessageBox::Cancel:*/
		default:	{
			return false;
		}
		}
	}

	if ( doc->isHidden() == false )
	{
		int id = doc->id();
		QString s_name = doc->documentName();
		emit uniq_->docClosing( doc );
		um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
					"The document %1 - [%2] was closed.\n" )
				.arg( s_name )
				.arg( id )
				);
	}

	delete doc; /* will remove the document from CpgLibrary's list */
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::saveDocument		(
		BBlocks::UserMsg & um, CpgDoc * doc, IDrawFile * format,
		const BBlocks::Version3D & version, const QString & s_file,
		bool b_force_choose, bool b_update_data )
{

	doc = normaliseDoc( um, doc );
	if ( doc == NULL )
		return false;

	if ( format == NULL )
	{
		format = FormatManager::defaultInst();
		if ( format == NULL )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"There is no default format selected." )
					);
			return false;
		}
	}

	/* where to save */
	QString	s_path = s_file;
	for ( ;; )
	{
		if ( b_force_choose == false )
		{
			if ( s_path.isEmpty() == false )
				break;
			s_path = doc->filePath();
			if ( s_path.isEmpty() == false )
				break;
		}
		s_path = QFileDialog::getSaveFileName(
					activeWindow(),
					QObject::tr( "Select file name and location:" ),
					doc->filePath(),
					format->getExtDec()
					);
		if ( s_path.isEmpty() )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"User cancelled the save command.." )
					);
			return false;
		}
		break;
	}


	/* now ask the manager to save it */
	if ( format->save( doc, s_path, version, um ) == false )
	{
		return false;
	}
	else
	{
		if ( b_update_data )
		{
			doc->setFilePath( s_path );
			doc->resetModified();

			CpgLibrary::uniq_->docSaved( doc );
		}


		um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
					"The document [%1] was saved as\n"
					"%2\n"
					"in %3 format, version %4.\n")
				.arg( doc->id() )
				.arg( s_path )
				.arg( format->name() )
				.arg( version.toString() )
				);



		return true;
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
PgSpace *		CpgLibrary::crtSpace			( void )
{
	if ( uniq_->crt_doc_ == NULL )
		return NULL;
	return uniq_->crt_doc_->currentSpace();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
PgSpace *		CpgLibrary::createSpace		(
		BBlocks::UserMsg & um, CpgDoc * doc, const QString & s_name )
{
	doc = normaliseDoc( um, doc );
	if ( doc == NULL )
		return NULL;

	QString s_final_name = s_name;
	if ( s_final_name.isEmpty() )
		s_final_name = doc->spaceUniqName();

	/* creates default values */
	PgSpace * space = new PgSpace( s_final_name );
	space->setAssocDoc( doc );

	/* performs the action */
	if ( ASpaceID::createSpace( um, doc, space ) == NULL )
	{
		delete space;
		return NULL;
	}

	return space;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
PgSpace *		CpgLibrary::createSpaceFromTempl		(
		BBlocks::UserMsg & um, CpgDoc * doc, PgSpace * s_tepl )
{
	doc = normaliseDoc( um, doc );
	if ( doc == NULL )
		return NULL;

	if ( s_tepl == NULL )
	{
		QString s_loc_f = QFileDialog::getOpenFileName(
					activeWindow(),
					QObject::tr( "Select the file to open:" )
					);
		if ( s_loc_f.isEmpty() )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"User cancelled the open command.\n" )
					);
			return NULL;
		}

		/** @todo use a guider;  select a space to use as template */
	}

	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::removeSpace		(
		BBlocks::UserMsg & um, CpgDoc * doc, PgSpace * space )
{
	return ( ASpaceID::deleteSpace( um, doc, space ) != NULL );
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::setCrtSpace		(
		BBlocks::UserMsg & um, CpgDoc * doc, PgSpace * the_space )
{

	doc = normaliseDoc( um, doc );
	if ( doc == NULL )
		return NULL;

	if ( doc->currentSpace() == the_space )
	{
		um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
					"The space %1 is already current in\n"
					"associated document [%2] - %3.\n")
				.arg( ( the_space == NULL ? "" : the_space->name() ) )
				.arg( doc->id() )
				.arg( doc->documentName() )
				);
		return false;
	}

	if ( the_space == NULL )
	{
		if ( doc->spaceCount() > 0 )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"Can't set current space to NULL in document [%1] - %2.\n")
					.arg( doc->id() )
					.arg( doc->documentName() )
					);
			return false;
		}
		doc->setCurrentSpace( the_space );
		emit uniq_->crtSpaceChanged( the_space );

		um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
					"The document [%1] - %2 has no current space.\n")
				.arg( doc->id() )
				.arg( doc->documentName() )
				);
	}
	else
	{
		Q_ASSERT( doc == the_space->document() );
		doc->setCurrentSpace( the_space );
		emit uniq_->crtSpaceChanged( the_space );

		um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
					"The space %1 was made current in\n"
					"associated document [%2] - %3.\n")
				.arg( the_space->name() )
				.arg( doc->id() )
				.arg( doc->documentName() )
				);
	}

	return true;

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::addDocument		( CpgDoc * itm )
{
	if ( itm == NULL )
	{
		/* lame attempt :) */
		Q_ASSERT( false );
		return;
	}

	/* see if this document is part of our list already */
	int i = uniq_->lst_doc_.indexOf( itm );
	if ( i == -1 )
	{	/* it's pristine */

		/* add document to internal list */
		uniq_->lst_doc_.append( itm );
		if ( uniq_->crt_doc_ == NULL )
		{	/* setCrtDoc() checks for isHidden() flag, so we don't have to */
			setCrtDoc( itm );
		}

		/* connect this document's undo mechanism to main mechanism */
		uniq_->ug_.addStack( itm->undoStack() );

	}
	else
	{ /* can't add a document more than once, men */
		Q_ASSERT( false );
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::remDocument		( CpgDoc * itm )
{

	/* get the index of this document; if -1 is not ours */
	int i = uniq_->lst_doc_.indexOf( itm );
	if ( i != -1 )
	{

		CpgDoc *		new_itm = NULL;

		/* if this was current document, find a new, proper candidate */
		if ( uniq_->crt_doc_ == itm )
		{
			/* if there are documents in the list */
			if ( uniq_->lst_doc_.count() > 0 )
			{
				/* find one that is not hidden, walknig from back to front */
				int j = uniq_->lst_doc_.count() - 1;
				while ( j >= 0 )
				{
					new_itm = uniq_->lst_doc_.at( j );
					if ( new_itm->isHidden() == false )
					{ /* found one */
						if ( new_itm != itm )
							break;
					}
					j--;
				}

				/* if all remaining documents are hidden */
				if ( j == -1 )
				{ /* is like no documents left opened */
					new_itm = NULL;
					setCrtDoc( NULL );
				}
			}
			/* else no documents left opened */

			setCrtDoc( new_itm );
		}

		/* remove from the list */
		uniq_->lst_doc_.removeAt( i );

		/* disconnect this document's undo mechanism from main mechanism */
		uniq_->ug_.removeStack( itm->undoStack() );

	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc *			CpgLibrary::createNew		(
		const QString & s_path, BBlocks::UserMsg & um, bool b_vis )
{
	CpgDoc *	new_doc;

	if ( s_path.isEmpty() )
	{
		new_doc = new CpgDoc( b_vis );
		um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
					"A new document [%1] was created and made current.\n" )
				.arg( new_doc->id() )
				);
		new_doc->fileNew();
	}
	else
	{
		/* get the format */
		IDrawFile * format = FormatManager::defaultInst();
		if ( format == NULL )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"There is no default file format.\n" )
					);
			return NULL;
		}

		/* create the empty document */
		new_doc = new CpgDoc( b_vis );

		/* save the empty document */
		if ( format->save( new_doc, s_path, BBlocks::Version3D(), um ) == false )
		{
			um.add( BBlocks::UserMsgMgr::MSG_WARNING, QObject::tr(
						"New document [%1]\n"
						"was created in memory but could not be saved as\n"
						"%2.\n" )
					.arg( new_doc->id() )
					.arg( s_path )
					);
		}
		else
		{
			um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
						"A new document [%1]\nwas created,\n"
						"saved as %2\n"
						"and made current.\n" )
					.arg( new_doc->id() )
					.arg( s_path )
					);
			new_doc->setFilePath( s_path );
		}

	}
	CpgLibrary::addDocument( new_doc );
	emit uniq_->docEmerging( new_doc );

	/* becomes current document in the application */
	CpgLibrary::setCrtDoc( new_doc );

	return new_doc;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc *			CpgLibrary::openExisting		(
		const QString & s_file, BBlocks::UserMsg & um, bool b_vis )
{
	CpgDoc *		new_doc;
	QString		s_loc_f = s_file;

	if ( s_loc_f.isEmpty() )
	{ /* ask the user to provide a file */
		s_loc_f = QFileDialog::getOpenFileName(
					activeWindow(),
					QObject::tr( "Select the file to open:" )
					);
		if ( s_loc_f.isEmpty() )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"User cancelled the open command.\n" )
					);
			return NULL;
		}
	}

	/* see if already loaded */
	new_doc = CpgLibrary::docByFile( s_loc_f );
	if ( new_doc != NULL )
	{
		um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
					"File %1\nis already loaded as document [%2].\n" )
				.arg( s_loc_f )
				.arg( new_doc->id() )
				);
		return NULL;
	}

	/* go ahead and load */
	new_doc = new CpgDoc( b_vis );
	if ( new_doc->fileOpen( s_loc_f ) == false )
	{
		delete new_doc;
		new_doc = NULL;
	}
	else
	{
		/* becomes current document in the application */
		CpgLibrary::addDocument( new_doc );
		if ( b_vis )
		{
			emit CpgLibrary::uniq_->docEmerging( new_doc );
			CpgLibrary::setCrtDoc( new_doc );
			um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
						"File [%1]\nwas loaded as document [%2] and was made current.\n" )
					.arg( s_loc_f )
					.arg( new_doc->id() )
					);
		}
	}

	return new_doc;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::startClosing		( BBlocks::UserMsg & um )
{
	if ( uniq_->b_closing_ == false )
	{
		/* attempt to close all documents; abort if one can't be saved */
		if ( uniq_->closeAll() == false )
			return false;

		uniq_->b_closing_ = true;

		/* inform thirty party that we're dying */
		emit uniq_->closing();

		um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
					"The program is being shut down." )
				);
		um.show();
		BBlocks::UserMsgMgr::setOutputType( BBlocks::UserMsgMgr::MSGTY_DISABLED );
	}
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QWidget *		CpgLibrary::activeWindow		( void )
{
	return static_cast<QApplication*>( qApp )->activeWindow();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::getTempDir			( void )
{
	QDir	d( QDir::tempPath() );
	if ( d.exists() == false )
	{
		if ( d.mkpath(".") == false )
			return false;
	}
	QString s_pth( "./" CADPLAYG_NAME "/" CPG_VER_STR );
	if ( d.mkpath( s_pth ) )
	{
		d.cd( s_pth );
	}
	else
	{
		return false;
	}

	/* make sure we respect the advertised format */
	s_tmp_ = d.absolutePath();
	if ( s_tmp_.endsWith( '/' ) == false )
		s_tmp_.append( '/' );

	/* create specific directories */
	if ( d.exists( FILETAGSDIR ) == false )
	{
		if ( d.mkpath( FILETAGSDIR ) == false )
			return false;
	}

	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc *			CpgLibrary::docByName		( const QString & s_name )
{

	CpgDoc *	itr;

	if ( s_name.isEmpty() )
		return NULL;

	foreach( itr, uniq_->lst_doc_ )
	{
		if ( QString::compare( itr->documentName(), s_name, Qt::CaseInsensitive) == 0 )
		{
			return itr;
		}
	}
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc *			CpgLibrary::docByFile		( const QString & s_name )
{
	CpgDoc *	itr;

	if ( s_name.isEmpty() )
		return NULL;

	foreach( itr, uniq_->lst_doc_ )
	{
		if ( QString::compare( itr->filePath(), s_name, Qt::CaseInsensitive) == 0 )
		{
			return itr;
		}
	}
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
CpgDoc *			CpgLibrary::docById			( int id )
{
	CpgDoc *	itr;

	if ( id < 0 )
		return NULL;

	foreach( itr, uniq_->lst_doc_ )
	{
		if ( itr->id() == id )
		{
			return itr;
		}
	}
	return NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::close					( void )
{
	BBlocks::UserMsg		um;
	bool b = CpgLibrary::closeDoc( um );
	um.show();
	return b;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::closeAll					( void )
{
	BBlocks::UserMsg		um;
	bool		b = true;
	int i = lst_doc_.count() - 1;
	while ( i >= 0 )
	{
		b = CpgLibrary::closeDoc( um );
		if ( b == false )
		{
			break;
		}
		i--;
	}
	um.show();
	return b;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::copySel					( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::cutSel					( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::deleteSel				( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::exit						( void )
{
	BBlocks::UserMsg		um;
	CpgLibrary::startClosing( um );
	um.show();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::newFile					( void )
{
	BBlocks::UserMsg		um;
	CpgLibrary::createNew( QString(), um );
	um.show();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::newInstance				( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::open						( void )
{
	BBlocks::UserMsg		um;
	/*CpgDoc * new_doc = */CpgLibrary::openExisting( QString(), um );
	um.show();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::paste					( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::save						( void )
{
	BBlocks::UserMsg		um;
	CpgLibrary::saveDocument( um );
	um.show();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::saveAs					( void )
{
	BBlocks::UserMsg		um;
	CpgLibrary::saveDocument( um, NULL, NULL, BBlocks::Version3D(), QString(), true );
	um.show();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::setUndoLimit				( int new_lim )
{
	/* sanity checks */
	if ( new_lim < 0 )
		return;
	if ( new_lim > 100000 )
		new_lim = 100000;

	foreach( CpgDoc * iter, lst_doc_ )
	{
		iter->undoStack()->setUndoLimit( new_lim );
	}
	Prefs::set( Prefs::ATOMS_MAX_IN_DOC, (qint64)new_lim );
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::redo						( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void			CpgLibrary::undo						( void )
{
	/** @todo implement now */

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
PgLayer *		CpgLibrary::createLayer				(
		BBlocks::UserMsg & um, const QString & s_name, CpgDoc * doc, PgSpace * space )
{

	PgLayGlob *		glb_lay;
	PgLaySpc *		loc_lay;
	PgLayer *		layer = NULL;
	QString			final_name = s_name;


	if ( space == NULL )
	{ /* create global layer */
		glb_lay = new PgLayGlob( doc );
		layer = glb_lay;
		if ( final_name.isEmpty() )
		{
			final_name = space->layerUniqName();
		}
		space = doc->currentSpace();
	}
	else
	{ /* create local layer */
		Q_ASSERT( space->document() == doc );
		loc_lay = new PgLaySpc( space );
		layer = loc_lay;
		if ( final_name.isEmpty() )
		{
			final_name = doc->layerUniqName();
		}
	}
	layer->setName( final_name );
	if ( ALayID::createLayer( um, space, layer ) != NULL )
	{
		return layer;
	}
	else
	{
		delete layer;
		return NULL;
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::removeLayer				(
		BBlocks::UserMsg & um, PgSpace * space, PgLayer * layer )
{
	return ( ALayID::deleteLayer( um, space, layer ) != NULL );
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool			CpgLibrary::setCrtLayer				(
		BBlocks::UserMsg & um, PgSpace * the_space, PgLayer * the_layer )
{

	if ( the_space == NULL )
	{
		um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
					"Can't set current layer for NULL space.\n"
					)
				);
		return false;
	}

	if ( the_layer != NULL )
	{
		if ( the_layer->document() != the_space->document() )
		{
			um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
						"Layer %1 is part of document %2.\n"
						"We can not make it current in space %3,\n"
						"which is aprt of document %4.\n" )
					.arg( the_layer->name() )
					.arg( the_layer->document() == NULL ?
							  "NULL" :
							  the_layer->document()->documentName() )
					.arg( the_space->name() )
					.arg( the_space->document() == NULL ?
							  "NULL" :
							  the_space->document()->documentName() )
					);
			return false;
		}
		if ( the_layer->isGlobal() == false )
		{
			PgLaySpc * spc_lay = static_cast<PgLaySpc *>( the_layer );
			if ( spc_lay->space() != the_space )
			{
				um.add( BBlocks::UserMsgMgr::MSG_ERROR, QObject::tr(
							"Layer %1 is part of space %2.\n"
							"We can not make it current in space %3.\n" )
						.arg( the_layer->name() )
						.arg( spc_lay->space() == NULL ? "NULL" : spc_lay->space()->name() )
						.arg( the_space->name() )
						);
				return false;
			}
		}
	}

	the_space->setCurrentLayer( the_layer );

	um.add( BBlocks::UserMsgMgr::MSG_INFO, QObject::tr(
				"The layer %1 was made current in\n"
				"space %2, part of document [%3] - %4.\n")
			.arg( the_layer->name() )
			.arg( the_space->name() )
			.arg( the_layer->document()->id() )
			.arg( the_layer->document()->documentName() )
			);

	emit uniq_->crtLayerChanged( the_space, the_layer );

	/** @todo maybe an undo atom for this? */

	return false;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QString				CpgLibrary::lastPathComp				(
		const QString & full_path )
{
	int i = full_path.lastIndexOf( '/' ) + 1;
	QString s_ret = full_path.mid( i );
	i = s_ret.indexOf( '.' );
	if ( i != -1 )
	{
		return s_ret.mid( 0, i );
	}
	return s_ret;
}
/* ========================================================================= */

/*  CLASS    =============================================================== */
//
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */

